#include "ffmpegutils.h"
#include <QFile>
#include <QDebug>

FFmpegUtils::FFmpegUtils(){

}

void FFmpegUtils::convertRawVideo(RawVideoFrame &in, RawVideoFrame &out){
    int ret = 0;
    // 转换上下文
    SwsContext *ctx = nullptr;
    // 输入/输出缓冲区，元素指向每帧中每一个平面的数据
    uint8_t *inData[4], *outData[4];
    // 每个平面一行的大小
    int inStrides[4], outStrides[4];
    // 每一帧图片的大小
    int inFrameSize, outFrameSize;



    // 创建输入缓冲区
    ret = av_image_alloc(inData, inStrides, in.width, in.height, in.format, 1);
    if(ret < 0){
        char errbuf[1024];
        av_strerror(ret,errbuf,sizeof (errbuf));
        qDebug() << "av_image_alloc inData error:" << errbuf;
        goto end;
    }

    // 创建输出缓冲区
    ret = av_image_alloc(outData, outStrides, out.width, out.height, out.format, 1);
    if (ret < 0) {
        char errbuf[1024];
        av_strerror(ret, errbuf, sizeof (errbuf));
        qDebug() << "av_image_alloc outData error:" << errbuf;
        goto end;
    }

    // 创建转换上下文
    // 方式一：
    ctx = sws_getContext(in.width, in.height, in.format,
                         out.width, out.height, out.format,
                         SWS_BILINEAR, nullptr, nullptr, nullptr);
    if (!ctx) {
        qDebug() << "sws_getContext error";
        goto end;
    }

    // 方式二：
    // ctx = sws_alloc_context();
    // av_opt_set_int(ctx, "srcw", in.width, 0);
    // av_opt_set_int(ctx, "srch", in.height, 0);
    // av_opt_set_pixel_fmt(ctx, "src_format", in.format, 0);
    // av_opt_set_int(ctx, "dstw", out.width, 0);
    // av_opt_set_int(ctx, "dsth", out.height, 0);
    // av_opt_set_pixel_fmt(ctx, "dst_format", out.format, 0);
    // av_opt_set_int(ctx, "sws_flags", SWS_BILINEAR, 0);

    // if (sws_init_context(ctx, nullptr, nullptr) < 0) {
    //     qDebug() << "sws_init_context error";
    //     goto end;
    // }

    // 计算一帧图像大小
    inFrameSize = av_image_get_buffer_size(in.format, in.width, in.height, 1);
    outFrameSize = av_image_get_buffer_size(out.format, out.width, out.height, 1);

    // 输入
    // 拷贝输入像素数据到 inData[0]
    memcpy(inData[0], in.pixels, inFrameSize);

    // 每一帧的转换
    sws_scale(ctx, inData, inStrides, 0, in.height, outData, outStrides);

    // 拷贝像素数据到 outData[0]
    out.pixels = (char *)malloc(outFrameSize);
    memcpy(out.pixels, outData[0], outFrameSize);
end:
    av_freep(&inData[0]);
    av_freep(&outData[0]);
    sws_freeContext(ctx);
}

void FFmpegUtils::convertRawVideo(RawVideoFile &in, RawVideoFile &out){
    int ret = 0;
    // 转换上下文
    SwsContext *ctx = nullptr;
    // 输入/输出缓冲区，元素指向每帧中每一个平面的数据
    uint8_t *inData[4], *outData[4];
    // 每个平面一行的大小
    int inStrides[4], outStrides[4];
    // 每一帧图片的大小
    int inFrameSize, outFrameSize;

    // 输入文件
    QFile inFile(in.filename);
    // 输出文件
    QFile outFile(out.filename);

    // 创建输入缓冲区
    ret = av_image_alloc(inData, inStrides, in.width, in.height, in.format, 1);
    if(ret < 0){
        char errbuf[1024];
        av_strerror(ret,errbuf,sizeof (errbuf));
        qDebug() << "av_image_alloc inData error:" << errbuf;
        goto end;
    }

    // 创建输出缓冲区
    ret = av_image_alloc(outData, outStrides, out.width, out.height, out.format, 1);
    if (ret < 0) {
        char errbuf[1024];
        av_strerror(ret, errbuf, sizeof (errbuf));
        qDebug() << "av_image_alloc outData error:" << errbuf;
        goto end;
    }

    // 创建转换上下文
    // 方式一：
    ctx = sws_getContext(in.width, in.height, in.format,
                         out.width, out.height, out.format,
                         SWS_BILINEAR, nullptr, nullptr, nullptr);
    if (!ctx) {
        qDebug() << "sws_getContext error";
        goto end;
    }

    // 方式二：
    // ctx = sws_alloc_context();
    // av_opt_set_int(ctx, "srcw", in.width, 0);
    // av_opt_set_int(ctx, "srch", in.height, 0);
    // av_opt_set_pixel_fmt(ctx, "src_format", in.format, 0);
    // av_opt_set_int(ctx, "dstw", out.width, 0);
    // av_opt_set_int(ctx, "dsth", out.height, 0);
    // av_opt_set_pixel_fmt(ctx, "dst_format", out.format, 0);
    // av_opt_set_int(ctx, "sws_flags", SWS_BILINEAR, 0);

    // if (sws_init_context(ctx, nullptr, nullptr) < 0) {
    //     qDebug() << "sws_init_context error";
    //     goto end;
    // }

    if (!inFile.open(QFile::ReadOnly)) {
        qDebug() << "open in file failure";
        goto end;
    }

    if (!outFile.open(QFile::WriteOnly)) {
        qDebug() << "open out file failure";
        goto end;
    }

    // 计算一帧图像大小
    inFrameSize = av_image_get_buffer_size(in.format, in.width, in.height, 1);
    outFrameSize = av_image_get_buffer_size(out.format, out.width, out.height, 1);

    while (inFile.read((char *)inData[0], inFrameSize) == inFrameSize) {
        // 每一帧的转换
        sws_scale(ctx, inData, inStrides, 0, in.height, outData, outStrides);
        // 每一帧写入文件
        outFile.write((char *)outData[0], outFrameSize);
    }
end:
    inFile.close();
    outFile.close();
    av_freep(&inData[0]);
    av_freep(&outData[0]);
    sws_freeContext(ctx);
}
